using System;
using UnityEngine;
using UnityEngine.EventSystems;
using Yoozoo.UI.YGUI;

public class PrettyGirlsVirtualJoystick : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
    [SerializeField] private RectTransform m_background;
    [SerializeField] private RectTransform m_handle;
    [SerializeField] private YButton m_upButton;
    [SerializeField] private YButton m_downButton;
    [SerializeField] private YScrollbar m_scrollbar;
    [SerializeField] private YButton m_fovIncreaseButton;
    [SerializeField] private YButton m_fovDecreaseButton;

    private Vector2 m_joystickPosition = Vector2.zero;
    private Vector2 m_joystickCenter = Vector2.zero;

    public PrettyGirlsFreedomCinemachineCamera m_freedomCameraComponent;

    private bool m_joystickLock = false;
    private bool m_downButtonLock = false;
    private bool m_upButtonLock = false;
    private bool m_scrollbarLock = false;
    private bool m_fovIncreaseButtonLock = false;
    private bool m_fovDecreaseButtonLock = false;

    public int m_mode = 2;
    
    // Start is called before the first frame update
    void Start()
    {
        if (m_background == null)
        {
            Debug.LogError("m_background is null, please set it in the inspector");
            return;
        }

        if (m_handle == null)
        {
            Debug.LogError("m_handle is null, please set it in the inspector");
            return;
        }

        m_joystickCenter = m_handle.anchoredPosition;
        m_scrollbar.onValueChanged.AddListener(OnScrollbarValueChanged);

        PointDownUpRegister(m_upButton.gameObject, OnUpButtonDownHandler, OnUpButtonUpHandler);
        
        PointDownUpRegister(m_downButton.gameObject, OnDownButtonDownHandler, OnDownButtonUpHandler);
        
        PointDownUpRegister(m_scrollbar.gameObject, () =>
        {
            m_scrollbarLock = true;
        }, () =>
        {
            m_scrollbarLock = false;
        });
        
        PointDownUpRegister(m_fovIncreaseButton.gameObject, () =>
        {
            m_fovIncreaseButtonLock = true;
        }, () =>
        {
            m_fovIncreaseButtonLock = false;
        });
        
        PointDownUpRegister(m_fovDecreaseButton.gameObject, () =>
        {
            m_fovDecreaseButtonLock = true;
        }, () =>
        {
            m_fovDecreaseButtonLock = false;
        });
    }

    void Update()
    {
        if (m_fovIncreaseButtonLock)
        {
            m_scrollbar.value += 0.01f;
            if (m_scrollbar.value > 1) m_scrollbar.value = 1;
        }
        else if (m_fovDecreaseButtonLock)
        {
            m_scrollbar.value -= 0.01f;
            if (m_scrollbar.value < 0) m_scrollbar.value = 0;
        }
    }

    private void PointDownUpRegister(GameObject gameObject, Action downAction, Action upAction)
    {
        EventTrigger trigger = gameObject.GetOrAddComponent<EventTrigger>();
        EventTrigger.Entry pointerDownEntry = new EventTrigger.Entry
        {
            eventID = EventTriggerType.PointerDown
        };
        pointerDownEntry.callback.AddListener((data) =>
        {
            downAction?.Invoke();
        });
        trigger.triggers.Add(pointerDownEntry);
        EventTrigger.Entry pointerUpEntry = new EventTrigger.Entry
        {
            eventID = EventTriggerType.PointerUp
        };
        pointerUpEntry.callback.AddListener((data) =>
        {
            upAction?.Invoke();
        });
        trigger.triggers.Add(pointerUpEntry);
    }

    public void SetFreedomCameraComponent(PrettyGirlsFreedomCinemachineCamera freedomCameraComponent)
    {
        m_freedomCameraComponent = freedomCameraComponent;
        m_freedomCameraComponent.SetJoystick(this);
    }
    
    public void SetDefaultFovScrollbarValue(float value)
    {
        m_scrollbar.value = value;
    }

    public bool IsPointerOnUI()
    {
        return m_joystickLock || m_downButtonLock || m_upButtonLock || m_scrollbarLock || m_fovIncreaseButtonLock || m_fovDecreaseButtonLock;
    }

    private void OnUpButtonDownHandler()
    {
        m_upButtonLock = true;
        m_freedomCameraComponent.SetVerticalDirection(1);
    }

    private void OnUpButtonUpHandler()
    {
        m_upButtonLock = false;
        m_freedomCameraComponent.SetVerticalDirection(0);
    }

    private void OnDownButtonDownHandler()
    {
        m_downButtonLock = true;
        m_freedomCameraComponent.SetVerticalDirection(-1);
    }

    private void OnDownButtonUpHandler()
    {
        m_downButtonLock = false;
        m_freedomCameraComponent.SetVerticalDirection(0);
    }

    private void OnScrollbarValueChanged(float value)
    {
        m_freedomCameraComponent.SetFovScrollbarValue(value);
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        if (m_upButtonLock || m_downButtonLock) return;
        m_joystickLock = true;
        OnDrag(eventData);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        if (m_upButtonLock || m_downButtonLock) return;
        m_joystickLock = false;
        m_handle.anchoredPosition = m_joystickCenter;
        m_joystickPosition = Vector2.zero;
        m_freedomCameraComponent.SetJoystickDirection(GetJoystickDirection());
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (m_upButtonLock || m_downButtonLock) return;
        if (m_mode == 1)
        {
            OnDragHandler(eventData);
        }
        else
        {
            OnDragHandler2(eventData);
        }
    }

    public void ChangeMoveMode(int mode)
    {
        m_mode = mode;
    }

    private void OnDragHandler(PointerEventData eventData)
    {
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_background, eventData.position, eventData.pressEventCamera, out Vector2 localPoint))
        {
            Vector2 offset = localPoint - m_joystickCenter;
            float backgroundRadius = m_background.rect.width / 2;
            if (offset.magnitude > backgroundRadius)
            {
                offset = offset.normalized * backgroundRadius;
            }

            m_handle.anchoredPosition = m_joystickCenter + offset;
            m_joystickPosition = offset / backgroundRadius;
            m_freedomCameraComponent.SetJoystickDirection(GetJoystickDirection());
        }
    }

    private Vector2 GetJoystickDirection()
    {
        Vector2 joystickDirection = Vector2.zero;
        if (m_joystickPosition.y > 0)
        {
            joystickDirection += Vector2.up;
        }
        else if (m_joystickPosition.y < 0)
        {
            joystickDirection += Vector2.down;
        }

        if (m_joystickPosition.x > 0)
        {
            joystickDirection += Vector2.right;
        }
        else if (m_joystickPosition.x < 0)
        {
            joystickDirection += Vector2.left;
        }

        return joystickDirection;
    }
    
    private void OnDragHandler2(PointerEventData eventData)
    {
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(m_background, eventData.position, eventData.pressEventCamera, out Vector2 localPoint))
        {
            Vector2 offset = localPoint - m_joystickCenter;
            float backgroundRadius = m_background.rect.width / 2;

            if (Mathf.Abs(offset.x) > Mathf.Abs(offset.y))
            {
                offset.y = 0; // 只保留水平分量
            }
            else
            {
                offset.x = 0; // 只保留垂直分量
            }
            if (offset.magnitude > backgroundRadius)
            {
                offset = offset.normalized * backgroundRadius;
            }

            m_handle.anchoredPosition = m_joystickCenter + offset;
            m_joystickPosition = offset / backgroundRadius;

            m_freedomCameraComponent.SetJoystickDirection(GetJoystickDirection());
        }
    }
    
    private Vector2 GetJoystickDirection2()
    {
        Vector2 joystickDirection = Vector2.zero;
        if (Mathf.Abs(m_joystickPosition.x) > Mathf.Abs(m_joystickPosition.y))
        {
            joystickDirection = m_joystickPosition.x > 0 ? Vector2.right : Vector2.left;
        }
        else
        {
            joystickDirection = m_joystickPosition.y > 0 ? Vector2.up : Vector2.down;
        }
        return joystickDirection;
    }
}
